address_total = 0
hex_total = []
build_state = 0
# name: address
constant_register = {

}


def add_constant(name, dwords):
    """

    :param dwords:
    :param name: parameter name
    :return:
    """
    global constant_register, address_total, hex_total
    constant_register[name] = address_total
    address_total += len(dwords)
    hex_total.extend(dwords)


def words2dwords_hex(words, size):
    res = []
    for i in range(0, size, 2):
        tmp = (words[i + 1] << 32) + words[i]
        res.append('%016x' % tmp)
    return res


def build_constant_register():
    global address_total, hex_total, constant_register
    address_total = 0
    hex_total = []
    constant_register = {}

    zeros = [0] * 16
    add_constant('zeros', words2dwords_hex(zeros, len(zeros)))

    ones = [0] * 16
    ones[0] = 1
    add_constant('BN_1', words2dwords_hex(ones, len(ones)))

    G_mont = [
        0xF418029E, 0x61328990, 0xDCA6C050, 0x3E7981ED, 0xAC24C3C3, 0xD6A1ED99, 0xE1C13B05, 0x91167A5E,
        0x3C2D0DDD, 0xC1354E59, 0x8D3295FA, 0xC1F5E578, 0x6E2A48F8, 0x8D4CFB06, 0x81D735BD, 0x63CD65D4,
        0x00000001, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001
    ]
    q = [
        0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE]
    q_sub_2 = [
        0xFFFFFFFD, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE
    ]
    bn1_mq_mont = [
        0x00000001, 0x00000000, 0xFFFFFFFF, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000001
    ]
    rrq = [
        3, 2, 0xFFFFFFFF, 2, 1, 1, 2, 4
    ]
    qc = [1, 0]

    n = [
        0x39D54123, 0x53BBF409, 0x21C6052B, 0x7203DF6B,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE]
    n_sub_2 = [
        0x39D54121, 0x53BBF409, 0x21C6052B, 0x7203DF6B,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE
    ]
    bn1_mn_mont = [
        0xC62ABEDD, 0xAC440BF6, 0xDE39FAD4, 0x8DFC2094,
        0x00000000, 0x00000000, 0x00000000, 0x00000001
    ]
    rrn = [
        0x7C114F20, 0x901192AF, 0xDE6FA2FA, 0x3464504A,
        0x3AFFE0D4, 0x620FC84C, 0xA22B3D3B, 0x1EB5E412
    ]
    nc = [0x72350975, 0x327F9E88]

    add_constant('sm2_256_G_mont', words2dwords_hex(G_mont, len(G_mont)))

    add_constant('sm2_256_q', words2dwords_hex(q, len(q)))
    add_constant('sm2_256_q_sub2', words2dwords_hex(q_sub_2, len(q_sub_2)))
    add_constant('sm2_256_BN_1mq_mont', words2dwords_hex(bn1_mq_mont, len(bn1_mq_mont)))
    add_constant('sm2_256_rrq', words2dwords_hex(rrq, len(rrq)))
    add_constant('qc', words2dwords_hex(qc, len(qc)))

    add_constant('sm2_256_n', words2dwords_hex(n, len(n)))
    add_constant('sm2_256_n_sub2', words2dwords_hex(n_sub_2, len(n_sub_2)))
    add_constant('sm2_256_BN_1mn_mont', words2dwords_hex(bn1_mn_mont, len(bn1_mn_mont)))
    add_constant('sm2_256_rrn', words2dwords_hex(rrn, len(rrn)))
    add_constant('nc', words2dwords_hex(nc, len(nc)))

    pri_key = [
        0x15897263, 0x0c23661d, 0x171b1b65, 0x2a519a55,
        0x3dff7979, 0x068c8d80, 0xbd433c6c, 0x128b2fa8
    ]
    add_constant('sm2_test_prikey', words2dwords_hex(pri_key, len(pri_key)))

    global build_state
    build_state = 1


def gen_ram_coe_file():
    with open('ram.coe', 'w') as f:
        f.write('memory_initialization_radix=16;\n')
        f.write('memory_initialization_vector=\n')
        for data in hex_total:
            f.write(str(data) + ',\n')


def get_constant_address_by_name(name):
    global build_state
    if build_state != 1:
        build_constant_register()
    return constant_register[name]


if __name__ == '__main__':
    build_constant_register()
    gen_ram_coe_file()
    for item in constant_register.items():
        print(item)
